package com.fsd.core.wechat.util;

import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONObject;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fsd.core.common.BusinessException;
import com.fsd.core.wechat.entity.message.resp.Article;
import com.fsd.core.wechat.entity.message.resp.NewsMessage;
import com.fsd.core.wechat.entity.message.resp.TextMessage;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

/**
 * 消息工具类
 */

public class MessageUtil {
	private static Logger log = LoggerFactory.getLogger(MessageUtil.class);
	
	/** 
     * 返回消息类型：文本 
     */  
    public static final String RESP_MESSAGE_TYPE_TEXT = "text";  
  
    /** 
     * 返回消息类型：音乐 
     */  
    public static final String RESP_MESSAGE_TYPE_MUSIC = "music";  
  
    /** 
     * 返回消息类型：图文 
     */  
    public static final String RESP_MESSAGE_TYPE_NEWS = "news";  
  
    /** 
     * 请求消息类型：文本 
     */  
    public static final String REQ_MESSAGE_TYPE_TEXT = "text";  
  
    /** 
     * 请求消息类型：图片 
     */  
    public static final String REQ_MESSAGE_TYPE_IMAGE = "image";  
  
    /** 
     * 请求消息类型：链接 
     */  
    public static final String REQ_MESSAGE_TYPE_LINK = "link";  
  
    /** 
     * 请求消息类型：地理位置 
     */  
    public static final String REQ_MESSAGE_TYPE_LOCATION = "location";  
  
    /** 
     * 请求消息类型：音频 
     */  
    public static final String REQ_MESSAGE_TYPE_VOICE = "voice";  
  
    /** 
     * 请求消息类型：推送 
     */  
    public static final String REQ_MESSAGE_TYPE_EVENT = "event";  
  
    /** 
     * 事件类型：subscribe(订阅) 
     */  
    public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";  
  
    /** 
     * 事件类型：unsubscribe(取消订阅) 
     */  
    public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";  
  
    /** 
     * 事件类型：CLICK(自定义菜单点击事件) 
     */  
    public static final String EVENT_TYPE_CLICK = "CLICK";

	/**
	 * 事件类型：SCAN(带参数的二维码扫描事件)
	 */
	public static final String EVENT_TYPE_SCAN = "SCAN";
    
    private static Map<String, String> messageMap = null;
    public static void checkMessage(String message, JSONObject jsonObject) throws BusinessException{
    	if (!jsonObject.containsKey("errcode"))
    		return;
    	String errcode = jsonObject.getString("errcode");
    	String errmsg = jsonObject.getString("errmsg");
    	if (messageMap == null || messageMap.size() == 0){
    		messageMap = new HashMap<String, String>();
//    		messageMap.put("0", "请求成功");
    		messageMap.put("-1", "系统繁忙，此时请开发者稍候再试");
    		messageMap.put("40001", "获取access_token时AppSecret错误，或者access_token无效。请开发者认真比对AppSecret的正确性，或查看是否正在为恰当的公众号调用接口");
    		messageMap.put("40002", "不合法的凭证类型");
    		messageMap.put("40003", "不合法的OpenID，请开发者确认OpenID（该用户）是否已关注公众号，或是否是其他公众号的OpenID");
    		messageMap.put("40004", "不合法的媒体文件类型");
    		messageMap.put("40005", "不合法的文件类型");
    		messageMap.put("40006", "不合法的文件大小");
    		messageMap.put("40007", "不合法的媒体文件id");
    		messageMap.put("40008", "不合法的消息类型");
    		messageMap.put("40009", "不合法的图片文件大小");
    		messageMap.put("40010", "不合法的语音文件大小");
    		messageMap.put("40011", "不合法的视频文件大小");
    		messageMap.put("40012", "不合法的缩略图文件大小");
    		messageMap.put("40013", "不合法的AppID，请开发者检查AppID的正确性，避免异常字符，注意大小写");
    		messageMap.put("40014", "不合法的access_token，请开发者认真比对access_token的有效性（如是否过期），或查看是否正在为恰当的公众号调用接口");
    		messageMap.put("40015", "不合法的菜单类型");
    		messageMap.put("40016", "不合法的按钮个数");
    		messageMap.put("40017", "不合法的按钮个数");
    		messageMap.put("40018", "不合法的按钮名字长度");
    		messageMap.put("40019", "不合法的按钮KEY长度");
    		messageMap.put("40020", "不合法的按钮URL长度");
    		messageMap.put("40021", "不合法的菜单版本号");
    		messageMap.put("40022", "不合法的子菜单级数");
    		messageMap.put("40023", "不合法的子菜单按钮个数");
    		messageMap.put("40024", "不合法的子菜单按钮类型");
    		messageMap.put("40025", "不合法的子菜单按钮名字长度");
    		messageMap.put("40026", "不合法的子菜单按钮KEY长度");
    		messageMap.put("40027", "不合法的子菜单按钮URL长度");
    		messageMap.put("40028", "不合法的自定义菜单使用用户");
    		messageMap.put("40029", "不合法的oauth_code");
    		messageMap.put("40030", "不合法的refresh_token");
    		messageMap.put("40031", "不合法的openid列表");
    		messageMap.put("40032", "不合法的openid列表长度");
    		messageMap.put("40033", "不合法的请求字符，不能包含\\uxxxx格式的字符");
    		messageMap.put("40035", "不合法的参数");
    		messageMap.put("40038", "不合法的请求格式");
    		messageMap.put("40039", "不合法的URL长度");
    		messageMap.put("40050", "不合法的分组id");
    		messageMap.put("40051", "分组名字不合法");
    		messageMap.put("40055", "按钮url无效域");
    		messageMap.put("40117", "分组名字不合法");
    		messageMap.put("40118", "media_id大小不合法");
    		messageMap.put("40119", "button类型错误");
    		messageMap.put("40120", "button类型错误");
    		messageMap.put("40121", "不合法的media_id类型");
    		messageMap.put("40132", "微信号不合法");
    		messageMap.put("40137", "不支持的图片格式");
    		messageMap.put("41001", "缺少access_token参数");
    		messageMap.put("41002", "缺少appid参数");
    		messageMap.put("41003", "缺少refresh_token参数");
    		messageMap.put("41004", "缺少secret参数");
    		messageMap.put("41005", "缺少多媒体文件数据");
    		messageMap.put("41006", "缺少media_id参数");
    		messageMap.put("41007", "缺少子菜单数据");
    		messageMap.put("41008", "缺少oauth code");
    		messageMap.put("41009", "缺少openid");
    		messageMap.put("42001", "access_token超时，请检查access_token的有效期，请参考基础支持-获取access_token中，对access_token的详细机制说明");
    		messageMap.put("42002", "refresh_token超时");
    		messageMap.put("42003", "oauth_code超时");
    		messageMap.put("43001", "需要GET请求");
    		messageMap.put("43002", "需要POST请求");
    		messageMap.put("43003", "需要HTTPS请求");
    		messageMap.put("43004", "需要接收者关注");
    		messageMap.put("43005", "需要好友关系");
    		messageMap.put("44001", "多媒体文件为空");
    		messageMap.put("44002", "POST的数据包为空");
    		messageMap.put("44003", "图文消息内容为空");
    		messageMap.put("44004", "文本消息内容为空");
    		messageMap.put("45001", "多媒体文件大小超过限制");
    		messageMap.put("45002", "消息内容超过限制");
    		messageMap.put("45003", "标题字段超过限制");
    		messageMap.put("45004", "描述字段超过限制");
    		messageMap.put("45005", "链接字段超过限制");
    		messageMap.put("45006", "图片链接字段超过限制");
    		messageMap.put("45007", "语音播放时间超过限制");
    		messageMap.put("45008", "图文消息超过限制");
    		messageMap.put("45009", "接口调用超过限制");
    		messageMap.put("45010", "创建菜单个数超过限制");
    		messageMap.put("45015", "回复时间超过限制");
    		messageMap.put("45016", "系统分组，不允许修改");
    		messageMap.put("45017", "分组名字过长");
    		messageMap.put("45018", "分组数量超过上限");
    		messageMap.put("46001", "不存在媒体数据");
    		messageMap.put("46002", "不存在的菜单版本");
    		messageMap.put("46003", "不存在的菜单数据");
    		messageMap.put("46004", "不存在的用户");
    		messageMap.put("47001", "解析JSON/XML内容错误");
    		messageMap.put("48001", "api功能未授权，请确认公众号已获得该接口，可以在公众平台官网-开发者中心页中查看接口权限");
    		messageMap.put("50001", "用户未授权该api");
    		messageMap.put("50002", "用户受限，可能是违规后接口被封禁");
    		messageMap.put("61451", "参数错误(invalid parameter)");
    		messageMap.put("61452", "无效客服账号(invalid kf_account)");
    		messageMap.put("61453", "客服帐号已存在(kf_account exsited)");
    		messageMap.put("61454", "客服帐号名长度超过限制(仅允许10个英文字符，不包括@及@后的公众号的微信号)(invalid kf_acount length)");
    		messageMap.put("61455", "客服帐号名包含非法字符(仅允许英文+数字)(illegal character in kf_account)");
    		messageMap.put("61456", "客服帐号个数超过限制(10个客服账号)(kf_account count exceeded)");
    		messageMap.put("61457", "无效头像文件类型(invalid file type)");
    		messageMap.put("61450", "系统错误(system error)");
    		messageMap.put("61500", "日期格式错误");
    		messageMap.put("61501", "日期范围错误");
    		messageMap.put("9001001", "POST数据参数不合法");
    		messageMap.put("9001002", "远端服务不可用");
    		messageMap.put("9001003", "Ticket不合法");
    		messageMap.put("9001004", "获取摇周边用户信息失败");
    		messageMap.put("9001005", "获取商户信息失败");
    		messageMap.put("9001006", "获取OpenID失败");
    		messageMap.put("9001007", "上传文件缺失");
    		messageMap.put("9001008", "上传素材的文件类型不合法");
    		messageMap.put("9001009", "上传素材的文件尺寸不合法");
    		messageMap.put("9001010", "上传失败");
    		messageMap.put("9001020", "帐号不合法");
    		messageMap.put("9001021", "已有设备激活率低于50%，不能新增设备");
    		messageMap.put("9001022", "设备申请数不合法，必须为大于0的数字");
    		messageMap.put("9001023", "已存在审核中的设备ID申请");
    		messageMap.put("9001024", "一次查询设备ID数量不能超过50");
    		messageMap.put("9001025", "设备ID不合法");
    		messageMap.put("9001026", "页面ID不合法");
    		messageMap.put("9001027", "页面参数不合法");
    		messageMap.put("9001028", "一次删除页面ID数量不能超过10");
    		messageMap.put("9001029", "页面已应用在设备中，请先解除应用关系再删除");
    		messageMap.put("9001030", "一次查询页面ID数量不能超过50");
    		messageMap.put("9001031", "时间区间不合法");
    		messageMap.put("9001032", "保存设备与页面的绑定关系参数错误");
    		messageMap.put("9001033", "门店ID不合法");
    		messageMap.put("9001034", "设备备注信息过长");
    		messageMap.put("9001035", "设备申请参数不合法");
    		messageMap.put("9001036", "查询起始值begin不合法");
    	}
    	if (messageMap.containsKey(errcode)){
    		log.error("微信返回值，错误消息  errcode:{} errmsg:{}", errcode, errmsg); 
			throw new BusinessException(message + "：" + errcode + "-" + messageMap.get(errcode) + "-" + errmsg);
    	}
    }
  
    /** 
     * 解析微信发来的请求（XML） 
     *  
     * @param request 
     * @return 
     * @throws Exception 
     */  
    @SuppressWarnings("unchecked")  
    public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {  
        // 将解析结果存储在HashMap中  
        Map<String, String> map = new HashMap<String, String>();  
  
        // 从request中取得输入流  
        InputStream inputStream = request.getInputStream();  
        // 读取输入流  
        SAXReader reader = new SAXReader();  
        Document document = reader.read(inputStream);  
        // 得到xml根元素  
        Element root = document.getRootElement();  
        // 得到根元素的所有子节点  
        List<Element> elementList = root.elements();  
  
        // 遍历所有子节点  
        for (Element e : elementList)  
            map.put(e.getName(), e.getText());  
  
        // 释放资源  
        inputStream.close();  
        inputStream = null;  
  
        return map;  
    }  
  
    /** 
     * 文本消息对象转换成xml 
     *  
     * @param textMessage 文本消息对象 
     * @return xml 
     */  
    public static String textMessageToXml(TextMessage textMessage) {  
        xstream.alias("xml", textMessage.getClass());  
        return xstream.toXML(textMessage);  
    }  
  
    /** 
     * 音乐消息对象转换成xml 
     *  
     * @param musicMessage 音乐消息对象 
     * @return xml 
     */  
   /* public static String musicMessageToXml(MusicMessage musicMessage) {  
        xstream.alias("xml", musicMessage.getClass());  
        return xstream.toXML(musicMessage);  
    }  */
  
    /** 
     * 图文消息对象转换成xml 
     *  
     * @param newsMessage 图文消息对象 
     * @return xml 
     */  
    public static String newsMessageToXml(NewsMessage newsMessage) {  
        xstream.alias("xml", newsMessage.getClass());  
        xstream.alias("item", new Article().getClass());  
        return xstream.toXML(newsMessage);  
    }  

    /** 
     * 扩展xstream，使其支持CDATA块 
     *  
     */  
    private static XStream xstream = new XStream(new XppDriver() {  
        public HierarchicalStreamWriter createWriter(Writer out) {  
            return new PrettyPrintWriter(out) {  
                // 对所有xml节点的转换都增加CDATA标记  
                boolean cdata = true;
                @SuppressWarnings("rawtypes")
				public void startNode(String name, Class clazz) {  
                    super.startNode(name, clazz);
                }  
  
                protected void writeText(QuickWriter writer, String text) {  
                    if (cdata) {  
                        writer.write("<![CDATA[");  
                        writer.write(text);  
                        writer.write("]]>");  
                    } else {  
                        writer.write(text);  
                    }  
                }  
            };  
        }  
    });
}
